﻿using System;
using System.Data;

namespace Fingerbrisk.DataSource.FluentDatasourceInteract.SqlServer
{
    public class SqlTransaction : ITransaction
    {
        private readonly SqlSource _sqlSource;
        private readonly System.Data.SqlClient.SqlTransaction _transaction;
        private readonly object _lock = new object();

        internal SqlTransaction(SqlSource sqlSource)
        {
            if (sqlSource != null && sqlSource.State == ConnectionState.Open)
            {
                _sqlSource = sqlSource;
                _transaction = sqlSource.Connection.BeginTransaction();

                State = TransactionState.Open;
            }
            else
            {
                throw new Exception("Cannot create transaction on the source which is not in Open state");
            }
        }

        #region ITransaction Members

        public int Id
        {
            get;
            internal set;
        }

        public IFluentSource Source
        {
            get { return _sqlSource; }
        }

        public TransactionState State
        {
            get;
            internal set;
        }

        public bool Commit()
        {
            if (State != TransactionState.Open)
                return false;

            lock (_lock)
            {
                if (State != TransactionState.Open)
                    return false;

                _transaction.Commit();

                State = TransactionState.Commited;
                return true;
            }
        }

        public bool Rollback()
        {
            if (State != TransactionState.Open)
                return false;

            _transaction.Rollback();

            lock (_lock)
            {
                if (State != TransactionState.Open)
                    return false;

                State = TransactionState.Rolledback;
                return true;
            }
        }

        #endregion

        #region IDisposable Members

        public void Dispose()
        {
            Commit();
        }

        #endregion
    }
}
